package com.suredy.app.porject.model;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springframework.format.annotation.DateTimeFormat;

import com.suredy.app.porject.constants.BidStatus;
import com.suredy.app.porject.constants.FlowStatus;
import com.suredy.app.porject.constants.MoneyType;
import com.suredy.app.porject.constants.QuotationType;
import com.suredy.app.porject.constants.UserFileType;
import com.suredy.app.porject.model.embedded.BidAgencyInfo;
import com.suredy.app.porject.model.embedded.BiddingerInfo;
import com.suredy.app.porject.model.sp.Money;
import com.suredy.core.model.BaseModel;

/**
 * 投标模型
 * 
 * @author VIVID.G
 * @since 2015-10-12
 * @version v0.1
 */
@Entity
@Table(name = "tb_bid")
public class Bid extends BaseModel {

	private static final long serialVersionUID = 1L;

	/* 报价方式 */
	@Column(length = 50, nullable = false)
	private String quotationType;

	/* 项目名称 */
	@Column(length = 500, nullable = false)
	private String name;

	/* 投标编号 */
	@Column(name = "project_no", length = 100, nullable = false, unique = true)
	private String projectNo;

	/* 招标编号 */
	@Column(name = "bid_no", length = 100, unique = true)
	private String bidNo;

	/* 委托代理人 */
	@Column(length = 30)
	private String executor;

	/* 招标类型 */
	@Column(name = "bid_type", length = 100, nullable = false)
	private String bidType;

	/* 投标方式 */
	@Column(name = "bid_way", length = 100, nullable = false)
	private String bidWay;

	/* 报名时间 */
	@Column(name = "sign_date", nullable = false)
	@DateTimeFormat(pattern = "yyyy-MM-dd")
	private Date signDate;

	/* 开标时间 */
	@Column(name = "opening_time", nullable = false)
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
	private Date openingTime;

	/* 投标状态 */
	@Column(length = 20)
	@Enumerated(EnumType.STRING)
	private BidStatus status;

	/* 所属公司 */
	@Column(name = "own_company", length = 200, nullable = false)
	private String ownCompany;

	/* 招标单位信息 */
	@Embedded
	private BiddingerInfo biddingerInfo;

	/* 招标代理机构信息 */
	@Embedded
	private BidAgencyInfo bidAgencyInfo;

	/* 招标范围 */
	@Column(length = 3000, nullable = false)
	private String bidScope;

	/* 备注 */
	@Column(length = 3000)
	private String remark;

	/* 资金情况 */
	@OneToMany(mappedBy = "bid", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@Fetch(FetchMode.SUBSELECT)
	@OrderBy("gaveBack, time, name")
	private List<BidMoney> money;

	/* 招标文件 */
	@OneToMany(mappedBy = "bid", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@Fetch(FetchMode.SUBSELECT)
	@OrderBy("type, uploadTime, fileName")
	private List<BidFile> bidFiles;

	@OneToMany(mappedBy = "bid", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@Fetch(FetchMode.SUBSELECT)
	@OrderBy("time")
	private List<BidResult> result;

	@OneToMany(mappedBy = "bid", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@Fetch(FetchMode.SUBSELECT)
	@OrderBy("time")
	private List<FlowOfBid2User> flowInfo;

	/* 主合同 */
	@OneToOne(mappedBy = "bid", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	private Contract contract;

	/* 流程当前环节 */
	@Column(name = "flow_status", nullable = false)
	@Enumerated(EnumType.STRING)
	private FlowStatus flowStatus;

	// for search properties
	@Transient
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
	private Date openingTimeStart;
	@Transient
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
	private Date openingTimeEnd;

	public String getQuotationType() {
		return quotationType;
	}

	public void setQuotationType(String quotationType) {
		this.quotationType = quotationType;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getProjectNo() {
		return projectNo;
	}

	public void setProjectNo(String projectNo) {
		this.projectNo = projectNo;
	}

	public String getBidNo() {
		return bidNo;
	}

	public void setBidNo(String bidNo) {
		this.bidNo = bidNo;
	}

	public String getExecutor() {
		return executor;
	}

	public void setExecutor(String executor) {
		this.executor = executor;
	}

	public String getBidType() {
		return bidType;
	}

	public void setBidType(String bidType) {
		this.bidType = bidType;
	}

	public String getBidWay() {
		return bidWay;
	}

	public void setBidWay(String bidWay) {
		this.bidWay = bidWay;
	}

	public Date getSignDate() {
		return signDate;
	}

	public void setSignDate(Date signDate) {
		this.signDate = signDate;
	}

	public Date getOpeningTime() {
		return openingTime;
	}

	public void setOpeningTime(Date openingTime) {
		this.openingTime = openingTime;
	}

	public BidStatus getStatus() {
		return status;
	}

	public void setStatus(BidStatus status) {
		this.status = status;
	}

	public String getOwnCompany() {
		return ownCompany;
	}

	public void setOwnCompany(String ownCompany) {
		this.ownCompany = ownCompany;
	}

	public BiddingerInfo getBiddingerInfo() {
		return biddingerInfo;
	}

	public void setBiddingerInfo(BiddingerInfo biddingerInfo) {
		this.biddingerInfo = biddingerInfo;
	}

	public BidAgencyInfo getBidAgencyInfo() {
		return bidAgencyInfo;
	}

	public void setBidAgencyInfo(BidAgencyInfo bidAgencyInfo) {
		this.bidAgencyInfo = bidAgencyInfo;
	}

	public String getBidScope() {
		return bidScope;
	}

	public void setBidScope(String bidScope) {
		this.bidScope = bidScope;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public List<BidMoney> getMoney() {
		return money;
	}

	public void setMoney(List<BidMoney> money) {
		this.money = money;
	}

	public List<BidFile> getBidFiles() {
		return bidFiles;
	}

	public void setBidFiles(List<BidFile> bidFiles) {
		this.bidFiles = bidFiles;
	}

	public List<BidResult> getResult() {
		return result;
	}

	public void setResult(List<BidResult> result) {
		this.result = result;
	}

	public List<FlowOfBid2User> getFlowInfo() {
		return flowInfo;
	}

	public void setFlowInfo(List<FlowOfBid2User> flowInfo) {
		this.flowInfo = flowInfo;
	}

	public Contract getContract() {
		return contract;
	}

	public void setContract(Contract contract) {
		this.contract = contract;
	}

	public FlowStatus getFlowStatus() {
		return flowStatus;
	}

	public void setFlowStatus(FlowStatus flowStatus) {
		this.flowStatus = flowStatus;
	}

	public Date getOpeningTimeStart() {
		return openingTimeStart;
	}

	public void setOpeningTimeStart(Date openingTimeStart) {
		this.openingTimeStart = openingTimeStart;
	}

	public Date getOpeningTimeEnd() {
		return openingTimeEnd;
	}

	public void setOpeningTimeEnd(Date openingTimeEnd) {
		this.openingTimeEnd = openingTimeEnd;
	}

	// 以下是业务方法 //

	@Transient
	public BidResult getLastResult() {
		if (this.getResult() == null || this.getResult().isEmpty())
			return null;

		BidResult result = this.getResult().get(this.getResult().size() - 1);

		return result;
	}

	@Transient
	public List<Money> getOutMoney() {
		if (this.getMoney() == null)
			return null;

		List<Money> ret = new ArrayList<Money>();

		for (Money m : this.getMoney()) {
			if (!m.getPayOut())
				continue;

			ret.add(m);
		}

		return ret.isEmpty() ? null : ret;
	}

	@Transient
	public double getOutMoneyTotal() {
		if (this.getMoney() == null)
			return 0d;

		double ret = 0;

		for (Money m : this.getMoney()) {
			if (!m.getPayOut())
				continue;

			// 未到账
			if (!m.getInAccount())
				continue;

			// 已收回的资金不进行统计
			if (Boolean.TRUE.equals(m.getGaveBack()))
				continue;

			ret += m.getTotal();
		}

		return ret;
	}

	/**
	 * 获取投标保证金
	 * 
	 * @return
	 */
	@Transient
	public Money getTbbzj() {
		List<Money> out = this.getOutMoney();

		if (out == null || out.isEmpty())
			return null;

		for (Money m : out) {
			if (MoneyType.B_BZ.getValue().equals(m.getName()))
				return m;
		}

		return null;
	}

	@Transient
	public boolean isHasBidDoFile() {
		if (this.getBidFiles() == null || this.getBidFiles().isEmpty())
			return false;

		for (BidFile file : this.getBidFiles()) {
			if (UserFileType.F101_BID_DO_FILE.equals(file.getType()))
				return true;
		}

		return false;
	}

	@Transient
	public QuotationType getEnumQuotationType() {
		if (StringUtils.isBlank(this.getQuotationType()))
			return null;

		return QuotationType.getByValue(this.getQuotationType());
	}

	@Transient
	public String getQuotationString() {
		QuotationType qt = this.getEnumQuotationType();

		String str = qt.getValue();
		BidResult result = this.getLastResult();

		if (result == null)
			return "暂无报价";

		switch (qt) {
			case DROP_POINT:
			case SINGLE:
				str += "：" + result.getFinalMoneyDesc();
				break;
			case TOTAL:
				Double money = result.getFinalMoney();

				if (money == null)
					return str += "：暂无报价";

				str += "：" + this.numberFormat(money, "￥#.00");
				break;
		}

		if (!StringUtils.isBlank(result.getWinCompany()))
			str += "（中标公司：" + this.getLastResult().getWinCompany() + "）";

		return str;
	}

	/**
	 * 招标文件
	 * 
	 * @return
	 */
	@Transient
	public BidFile getServerFile() {
		return this.getFileOfType(UserFileType.F100_BID_SERVER_FILE);
	}

	/**
	 * 投标文件
	 * 
	 * @return
	 */
	@Transient
	public BidFile getDoFile() {
		return this.getFileOfType(UserFileType.F101_BID_DO_FILE);
	}

	/**
	 * 中标通知书
	 * 
	 * @return
	 */
	@Transient
	public BidFile getNoticeFile() {
		return this.getFileOfType(UserFileType.F103_BID_NOTICE_FILE);
	}

	/**
	 * 附件资料文件
	 * 
	 * @return
	 */
	@Transient
	public List<BidFile> getOtherFiles() {
		if (this.getBidFiles() == null || this.getBidFiles().isEmpty())
			return null;

		List<BidFile> ret = new ArrayList<BidFile>();

		for (BidFile f : this.getBidFiles()) {
			if (UserFileType.Z900_OTHER.equals(f.getType()))
				ret.add(f);
		}

		return ret.isEmpty() ? null : ret;
	}

	@Transient
	public boolean isPayoutMoneyCanBeRemove(String name) {
		if (StringUtils.isBlank(name))
			return false;

		MoneyType[] types = new MoneyType[] {MoneyType.B_GM, MoneyType.B_BZ, MoneyType.B_ZBFWF};

		for (MoneyType t : types) {
			if (name.equals(t.getValue()))
				return false;
		}

		return true;
	}

	private BidFile getFileOfType(UserFileType type) {
		if (this.getBidFiles() == null || this.getBidFiles().isEmpty())
			return null;

		if (type == null)
			return null;

		for (BidFile f : this.getBidFiles()) {
			if (type.equals(f.getType()))
				return f;
		}

		return null;
	}

	private String numberFormat(double number, String pattern) {
		NumberFormat nf = new DecimalFormat(pattern);

		return nf.format(number);
	}

}
